package com.htwy.ext;

import com.htwy.core.config.WebappConfig;
import com.htwy.core.model.Account;
import com.htwy.core.model.BaseModel;
import com.jfinal.core.Controller;
import com.jfinal.kit.Ret;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Page;
import java.util.HashMap;
import java.util.Map;
import org.apache.shiro.SecurityUtils;

/**
 * 基础控制器,实现了页面的基本功能
 * @param <M> 实现类所对应的泛型
 */
public abstract class BaseController<M extends BaseModel<M>> extends Controller {

    /**
     * 获取该类型对应的dao,需要实现类重写
     * @return dao
     */
    protected abstract M dao();

    /**
     * 从传入的参数获取泛型类的实例(用于对象的保存)
     * @return 类的实例
     */
    protected M getEntity(){
        return (M) getBean(dao().getClass(), WebappConfig.getConfig().get("entityPrefix", "entity"), true);
    }

    /**
     * 获取登录信息
     * @return 登录信息
     */
    protected Account getLogin() {
        if (WebappConfig.isUseShiro()) {
            Object account = SecurityUtils.getSubject().getPrincipal();
            return account == null ? null : (Account) account;
        }
        Account account = new Account();
        account.setUuid("0");
        account.setName("开发内部测试");
        account.setAccount("test");
        return account;
    }

    /**
     *  默认页面index.html
     */
    public void index(){
        renderTemplate("index.html");
    }

    /**
     * 通用获取查询条件方法(只支持UUID类型的单主键Modal)
     * 将所有传入的parameter转换成condition
     * @return 转换好的Map
     */
    protected Map<String,Object> getConditions(){
        Map<String,String[]> paraMap = getParaMap();
        Map<String,Object> conditions = new HashMap<>();
        for(String key:paraMap.keySet()){
            String[] values = paraMap.get(key);
            if(values.length == 1){
                conditions.put(key,values[0]);
            }else{
                conditions.put(key,values);
            }
        }
        return conditions;
    }

    /**
     * 通用列表方法(只支持UUID类型的单主键Modal)
     * 传入的参数(getConditions方法所需要的参数)
     */
    public void list(){
        renderJson(Ret.ok().set("data",dao().findByCondition(getConditions())));
    }

    /**
     * 通用列表方法(只支持UUID类型的单主键Modal)
     * 传入的参数(getConditions方法所需要的参数)
     */
    public void listNoCache(){
        renderJson(Ret.ok().set("data",dao().findByCondition(getConditions())));
    }

    /**
     * 通用分页方法(只支持UUID类型的单主键Modal)
     * 传入的参数(pageNumber,pageSize及getConditions方法所需要的参数)
     */
    public void paginate(){
        Page<M> page = dao().paginateByCondition(getConditions());

        renderJson(Ret.ok().set("total",page.getTotalRow()).set("rows",page.getList()));
    }

    /**
     * 通用加载方法(只支持UUID类型的单主键Modal)
     * 传入的参数(modal的主键名)
     */
    public void load(){
        renderJson(Ret.ok().set("data", dao().findById(getPara(dao().getPrimaryKey()))));
    }

    /**
     * 通用保存方法(只支持UUID类型的单主键Modal)
     * 传入的参数(modal的所有属性)
     */
    public void save(){
        M entity = getEntity();
        if(!beforeSave(entity)){
            return;
        }
        if (entity.hasPkValue()) {
            entity.update();
        } else {
            entity.set(entity.getPrimaryKey(), StrKit.getRandomUUID());
            entity.save();
        }
        if(!afterSave(entity)){
            return;
        }
        renderJson(Ret.ok().set("data",entity));
    }

    /**
     * 保存前对实例做某些处理,需要实现类重写
     * @param entity 要保存的实例
     * @return true:继续执行,false:中断执行
     */
    public boolean beforeSave(M entity){
        return true;
    }

    /**
     * 保存后对实例做某些处理,需要实现类重写
     * @param entity 已保存的实例
     * @return true:继续执行,false:中断执行
     */
    public boolean afterSave(M entity){
        return true;
    }

    /**
     * 通用删除方法
     */
    public void delete(){
        String pk = getPara(dao().getPrimaryKey());
        if(StrKit.notBlank(pk)){
            renderJson(Ret.ok().set("data", dao().deleteById(pk)));
        }else{
            renderJson(Ret.fail().set("msg","pk can not null"));
        }
    }

    /**
     * 通用删除多个的方法
     */
    public void batchDelete(){
        String[] pkArray = getParaValues(dao().getPrimaryKey() + WebappConfig.getConfig().get("idsSuffix", "s"));
        renderJson(Ret.ok().set("data", dao().deleteByPks(pkArray)));
    }

}
